<template>
    <div class="box">
        <el-card class="card">
            <el-form :inline="true" class="form">
                <el-form-item label="角色名称">
                    <el-input @keyup.enter.native="search" v-model="searchValue" placeholder="请输入角色名称"></el-input>
                </el-form-item>
                <el-form-item>
                    <el-button type="primary" @click="search" :disabled="searchValue ? false : true">搜索</el-button>
                    <el-button @click="reset" :disabled="searchValue ? false : true">重置</el-button>
                </el-form-item>
            </el-form>
        </el-card>

        <el-card>
            <el-button type="primary" @click="add" icon="plus">添加角色</el-button>
            <el-table :data="tableData" border stripe style="margin: 10px 0;">
                <el-table-column type="index" label="序号" width="80" align="center"></el-table-column>
                <el-table-column prop="id" label="id" width="80" align="center"></el-table-column>
                <el-table-column prop="roleName" label="角色名称" align="center" show-overflow-tooltip></el-table-column>
                <el-table-column prop="createTime" label="创建时间" align="center" show-overflow-tooltip></el-table-column>
                <el-table-column prop="updateTime" label="更新时间" align="center" show-overflow-tooltip></el-table-column>
                <el-table-column label="操作" align="center">
                    <template #="{ row, $index }">
                        <el-button type="warning" title="分配权限" size="small" @click="setPermisstion(row)"
                            icon="user"></el-button>
                        <el-button type="primary" title="编辑" size="small" @click="edit(row)" icon="edit"></el-button>
                        <el-button type="danger" title="删除" size="small" @click="deleteRole(row)"
                            icon="delete"></el-button>
                    </template>
                </el-table-column>
            </el-table>
            <el-pagination v-model:current-page="pageNum" v-model:page-size="pageSize" :page-sizes="[5, 10, 20, 30, 40]"
                :background="true" layout="prev, pager, next, jumper,->,sizes,total" :total="total"
                @size-change="handleSizeChange" @current-change="load" />

            <el-drawer v-model="drawer" title="分配权限">
                <el-tree ref="tree" style="max-width: 600px" :data="menuList" show-checkbox node-key="id"
                    default-expand-all :default-checked-keys="selectIds" :props="defaultProps" />
                <template #footer>
                    <div style="flex: auto">
                        <el-button @click="cancel1">取消</el-button>
                        <el-button type="primary" @click="confirm1">确定</el-button>
                    </div>
                </template>
            </el-drawer>

            <el-dialog :title="roleParams.id ? '更新角色' : '添加角色'" v-model="dialogvisible" width="36%">
                <el-form ref="form" :model="roleParams" style="margin: 10px 0;" :rules="rule">
                    <el-form-item label="角色名称" prop="roleName">
                        <el-input v-model="roleParams.roleName" placeholder="请输入角色名称"></el-input>
                    </el-form-item>
                </el-form>
                <template #footer>
                    <el-button @click="dialogvisible = false">取消</el-button>
                    <el-button type="primary" @click="confirm">确定</el-button>
                </template>
            </el-dialog>

        </el-card>
    </div>
</template>

<script setup lang="ts">
import { ref, onMounted, reactive, nextTick } from 'vue'
import { reqAllRoleList, reqAddOrUpdateRole, reqRemoveRole, reqAllMenuList, reqSetPermisstion } from '@/api/acl/role'
import type { RoleResponseData, Records, RoleData, MenuResponseData, MenuList } from '@/api/acl/role/type'
import { ElMessage, ElMessageBox } from 'element-plus'

let pageNum = ref<number>(1)
let pageSize = ref<number>(5)
let total = ref<number>(0)
let tableData = ref<Records>([])
let drawer = ref<boolean>(false)
let dialogvisible = ref<boolean>(false)
let searchValue = ref<string>('')
let form = ref<any>()
let roleParams = reactive<RoleData>({
    roleName: '',
})
let menuList = ref<MenuList>([])
let selectIds = ref<number[]>([])
let tree = ref<any>()
const defaultProps = {
    children: 'children',
    label: 'name',
}



const rule = {
    roleName:
        [
            { required: true, trigger: 'blur', message: '角色名称不能为空' },
            { min: 2, trigger: 'change', message: '长度至少两个字符' }
        ]
}

onMounted(() => {
    load()
})

const load = async (page = 1) => {
    pageNum.value = page
    let res: RoleResponseData = await reqAllRoleList(pageNum.value, pageSize.value, searchValue.value)
    if (res.code == 200) {
        total.value = res.data.total
        tableData.value = res.data.records
    }
}
const search = () => { load() }
const reset = () => { searchValue.value = '', load() }
const add = () => {
    dialogvisible.value = true
    Object.assign(roleParams, {
        roleName: '',
        id: undefined
    })
    nextTick(() => {
        form.value.clearValidate('roleName')
    })
}
const setPermisstion = async (row: RoleData) => {
    drawer.value = true
    Object.assign(roleParams, row)
    let res: MenuResponseData = await reqAllMenuList((roleParams.id as number))
    if (res.code == 200) {
        menuList.value = res.data
        selectIds.value = filterSelectArr(menuList.value, [])
    }
}
const filterSelectArr = (allData: any, initArr: any) => {
    allData.forEach((item: any) => {
        if (item.select && item.level == 4) {
            initArr.push(item.id)
        }
        if (item.children && item.children.length > 0) {
            filterSelectArr((item.children), initArr)
        }
    });
    return initArr
}
const cancel1 = () => {
    drawer.value = false
}
const confirm1 = async () => {
    const roleId = (roleParams.id as number)
    const ids = tree.value.getCheckedKeys()
    const ids1 = tree.value.getHalfCheckedKeys()
    let permisstionId = ids.concat(ids1)
    let res: any = await reqSetPermisstion(roleId, permisstionId)
    if (res.code == 200) {
        ElMessage({
            type: 'success',
            message: '分配成功'
        })
        window.location.reload()
    } else {
        ElMessage({
            type: 'error',
            message: '分配失败'
        })
    }
    drawer.value = false
}
const edit = (row: RoleData) => {
    dialogvisible.value = true
    Object.assign(roleParams, row)
    nextTick(() => {
        form.value.clearValidate('roleName')
    })
}
const deleteRole = async (row: RoleData) => {
    ElMessageBox.confirm(
        `你确定要删除角色${row.roleName}吗?`,
        'Warning',
        {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning',
        }
    )
        .then(async () => {
            let result = await reqRemoveRole((row.id as number))
            if (result.code == 200) {
                //删除成功提示信息
                ElMessage({
                    type: 'success',
                    message: '删除成功'
                });
                //再次获取已有的数据
                load(tableData.value.length > 1 ? pageNum.value : pageSize.value - 1)
            } else {
                ElMessage({
                    type: 'error',
                    message: '删除失败'
                })
            }
        })
        .catch(() => {
            ElMessage({
                type: 'info',
                message: '取消成功',
            })
        })
}
const confirm = async () => {
    //保证表单中各输入部件都校验通过再发请求
    await form.value.validate()

    let res: any = await reqAddOrUpdateRole(roleParams)
    if (res.code == 200) {
        ElMessage({
            type: 'success',
            message: roleParams.id ? '修改成功' : '添加成功'
        })
    } else {
        ElMessage({
            type: 'error',
            message: roleParams.id ? '修改失败' : '添加失败'
        })
    }
    dialogvisible.value = false
    load(roleParams.id ? pageNum.value : 1)
}
const handleSizeChange = () => { load() }
</script>

<style scoped lang="scss">
.form {
    display: flex;
    justify-content: space-between;
}

.card {
    height: 80px;
    margin-bottom: 10px;
}
</style>